import axios from 'axios'
import qs from 'qs'

const defaultServer = 'java'
// const defaultServer = 'mock'
const baseURL = {
  mock: '/mock-api',
  java: '/api'
}
const okCode = 0
// 设置默认的超时请求时间10秒
axios.defaults.timeout = 10000
// 设置CORS跨域请求允许携带资源凭证
axios.defaults.withCredentials = true
// 设置请求拦截器,用于在请求头中添加token
axios.interceptors.request.use(
  config => {
    const token = ''
    if (token) {
      config.headers.token = token
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)
// 自定义成功的外部状态码: 2XX 和 3XX 
axios.defaults.validateStatus = status => {
  return /^([2|3])\d{2}$/.test(status.toString())
}
// 设置响应拦截器,统一处理响应结果
axios.interceptors.response.use(
  response => {
    // 如果 response.data 的结构是 { code:__, message:__, data:__, ...},
    // 则将 response.data 的属性都挂载到 response 对象
    if (response.data && 'code' in response.data && 'message' in response.data && 'data' in response.data) {
      const resp = response.data
      for (const key in resp) {
        response[key] = resp[key]
      }
      if (resp.code === okCode) {
        response['ok'] = true
      } else {
        response['ok'] = false
        // 打印返回的内部状态码
        console.error(`错误码 ${resp.code}`)
        console.error(resp)
      }
    }
    return response
  },
  error => {
    const { response } = error
    if (response) {
      // 打印返回的外部状态码, 此时服务器返回了结果，但状态码不是2XX或3XX
      console.error(`错误码 ${response.status}`)
      console.error(response)
    } else {
      // 服务器没有返回结果
      if (!window.navigator.onLine) {
        // 如果发生断网
        console.error('网络连接已断开')
        return Promise.resolve({ ok: false, message: '请求超时' })
      }
    }
    return Promise.resolve({ ok: false, error })
  }
)

function buildURL(originalURL = '', server = defaultServer) {
  if (originalURL.startsWith('http')) {
    return originalURL
  } else {
    return baseURL[server] + originalURL
  }
}

// 表单方式提交 POST 请求
function post(url = '', data = {}, headers = {}, server = defaultServer) {
  return axios.post(buildURL(url, server), data, {
    transformRequest: data => qs.stringify(data),
    headers: Object.assign({ 'Content-Type': 'application/x-www-form-urlencoded' }, headers)
  })
}

// JSON 方式提交 POST 请求
function postJson(url = '', data = {}, headers = {}, server = defaultServer) {
  return axios.post(buildURL(url, server), data, {
    headers: Object.assign({ 'Content-Type': 'application/json' }, headers)
  })
}

// 二进制方式提交 POST 请求
function postBinary(url = '', binaryData, headers = {}, server = defaultServer) {
  const formData = new FormData()
  formData.append('file', binaryData)
  return axios.post(buildURL(url, server), formData, {
    headers: Object.assign({ 'Content-Type': 'multipart/form-data' }, headers),
    responseType: 'arraybuffer'
  })
}

function get(url = '', data = {}, headers = {}, server = defaultServer) {
  return axios.get(buildURL(url, server), { params: data, headers })
}

function del(url = '', data = {}, headers = {}, server = defaultServer) {
  return axios.delete(buildURL(url, server), { params: data, headers })
}

function patchJson(url = '', data = {}, headers = {}, server = defaultServer) {
  return axios.patch(buildURL(url, server), data, {
    headers: Object.assign({ 'Content-Type': 'application/json' }, headers)
  })
}

function putJson(url = '', data = {}, headers = {}, server = defaultServer) {
  return axios.put(buildURL(url, server), data, {
    headers: Object.assign({ 'Content-Type': 'application/json' }, headers)
  })
}

export { post, postJson, postBinary, get, del, patchJson, putJson, baseURL, okCode }
export default axios
